package net.jueb.custom.pojo;

import io.netty.util.CharsetUtil;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;

public class NMsg implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -8426290890045354261L;
	
	/**
	 * 协议头
	 */
	public final static byte head=0x08;
	/**
	 * 二层协议类型
	 */
	public byte secondProtocolType;
	/**
	 * 协议数据名称
	 * 大小0-127字节
	 */
	public String pojoName;
	/**
	 * 协议数据
	 * pojoData的大小不能超过2147483647-32767
	 * Integer.MAX_VALUE-Short.MAX_VALUE
	 */
	public byte[] pojoData;
	
	
	/**
	 * 
	 * @param secondProtocolType 二层协议类型
	 * @param pojoName 请求实体名称
	 * @param pojoData 请求实体数据
	 */
	public NMsg(byte secondProtocolType, String pojoName, byte[] pojoData) {
		super();
		this.secondProtocolType = secondProtocolType;
		this.pojoName = pojoName;
		this.pojoData = pojoData;
	}


	@Override
	public String toString() {
		return "NMsg [secondProtocolType=" + secondProtocolType + ", pojoName="
				+ pojoName + ", pojoData=" + pojoData.length + "bytes]";
	}


	/**
	 * 将此对象转换为字节数字
	 * 包含标记头和数据等新，开头没有总长度信息
	 * @return
	 * @throws Exception 
	 */
	public byte[] toByteArray() throws Exception
	{
		byte[] bytes=new byte[]{};
		ByteArrayOutputStream bos=new ByteArrayOutputStream();
		try {
			bos.write(head);//写入标记头
			bos.write(secondProtocolType);//写入二层协议类型
			
			int pojoNameLength=pojoName.getBytes(CharsetUtil.UTF_8).length;
			if(pojoNameLength>Byte.MAX_VALUE)
			{
				throw new RuntimeException("实体名称长度超出限制!pojoNameLength="+pojoNameLength);
			}
			bos.write(pojoNameLength);//写入实体名称长度
			
			bos.write(pojoName.getBytes(CharsetUtil.UTF_8));//写入实体名称数据
			
			int pojoDataLength=pojoData.length;
			if(pojoDataLength>(Integer.MAX_VALUE-Short.MAX_VALUE))
			{
				throw new RuntimeException("实体数据长度超出限制!pojoDataLength="+pojoDataLength);
			}
			
			bos.write(Integer2Bytes(pojoDataLength));//写入实体数据长度
			bos.write(pojoData);//写入实体数据
			bos.flush();
			bytes=bos.toByteArray();
		} catch (Exception e) {
			throw e;
		}
		return bytes;
	}
	
	/**
	 * int转字节数组 高位在前
	 * @param i
	 * @return
	 */
	public static byte[] Integer2Bytes(int i)
	{
		byte[] data=new byte[4];
		data[3]=(byte)(i&0xff);
		data[2]=(byte)((i>>8)&0xff);
		data[1]=(byte)((i>>16)&0xff);
		data[0]=(byte)((i>>24)&0xff);//右移24位，高8位
		return data;
	}
}
